package com.yzt.p_base.utils;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

/**
 * author : bob
 * date   : 2022/11/30
 * desc   :
 */
public class ZipUtils {

    /**
     * 1M Byte
     */
    private static final int BUFF_SIZE = 1024 * 1024;

    private static boolean stopZipFlag;

    /**
     * 批量压缩文件（夹）
     *
     * @param resFileList 要压缩的文件（夹）列表
     * @param zipFile     生成的压缩文件
     * @param zipListener zipListener
     */
    public static void zipFiles(Collection<File> resFileList, File zipFile, ZipListener zipListener) {

        try {
            ZipOutputStream zipout = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(
                    zipFile), BUFF_SIZE));
            for (File resFile : resFileList) {
                if (stopZipFlag) {
                    break;
                }
                zipFile(resFile, zipout, "", zipListener);
            }
            zipout.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 解压缩一个文件
     *
     * @param zipFile    压缩文件
     * @param folderPath 解压缩的目标目录
     */
    public static void upZipFile(File zipFile, String folderPath, OnZipCompleteListener listener) {

        try {
            ZipInputStream inZip = new ZipInputStream(new FileInputStream(zipFile));
            ZipEntry zipEntry;
            String szName = "";
            while ((zipEntry = inZip.getNextEntry()) != null) {
                szName = zipEntry.getName();
                if (szName.contains("../")) {
                    continue;
                }
                if (zipEntry.isDirectory()) {
                    // get the folder name of the widget
                    szName = szName.substring(0, szName.length() - 1);
                    File folder = new File(folderPath + File.separator + szName);
                    folder.mkdirs();
                } else {

                    File desFile = new File(folderPath + File.separator + szName);
                    if (!desFile.exists()) {
                        File fileParentDir = desFile.getParentFile();
                        if (!fileParentDir.exists()) {
                            fileParentDir.mkdirs();
                        }
                        desFile.createNewFile();
                    }
                    FileOutputStream out = new FileOutputStream(desFile);
                    int len;
                    byte[] buffer = new byte[1024];
                    while ((len = inZip.read(buffer)) != -1) {
                        out.write(buffer, 0, len);
                        out.flush();
                    }
                    out.close();
                }
            }
            inZip.close();

            if (listener != null) {
                listener.onComplete();
            }
        } catch (Exception e) {
            e.printStackTrace();

            if (listener != null) {
                listener.onError();
            }
        }
    }

    public interface OnZipCompleteListener {

        void onError();

        void onComplete();
    }

    /**
     * 压缩文件
     *
     * @param resFile  需要压缩的文件（夹）
     * @param zipout   压缩的目的文件
     * @param rootpath 压缩的文件路径
     */
    private static void zipFile(File resFile, ZipOutputStream zipout, String rootpath, ZipListener zipListener) {
        try {
            rootpath = rootpath + (rootpath.trim().length() == 0 ? "" : File.separator)
                    + resFile.getName();
            rootpath = new String(rootpath.getBytes(StandardCharsets.ISO_8859_1), "GB2312");
            if (resFile.isDirectory()) {
                File[] fileList = resFile.listFiles();
                int length = fileList.length;
                zipListener.zipProgress((int) ((1 / (float) (length + 1)) * 100));
                for (int i = 0; i < length; i++) {
                    if (stopZipFlag) {
                        break;
                    }
                    File file = fileList[i];
                    zipFile(file, zipout, rootpath, zipListener);
                    zipListener.zipProgress((int) (((i + 2) / (float) (length + 1)) * 100));
                }
            } else {
                byte[] buffer = new byte[BUFF_SIZE];
                BufferedInputStream in = new BufferedInputStream(new FileInputStream(resFile),
                        BUFF_SIZE);
                zipout.putNextEntry(new ZipEntry(rootpath));
                int realLength;
                while ((realLength = in.read(buffer)) != -1) {
                    if (stopZipFlag) {
                        break;
                    }
                    zipout.write(buffer, 0, realLength);
                }
                in.close();
                zipout.flush();
                zipout.closeEntry();
            }
        } catch (Exception ignored) {

        }
    }

    public interface ZipListener {
        void zipProgress(int zipProgress);
    }
}
